package com.aizuda.boot.modules.business.negotiation.aspect;

import com.aizuda.boot.modules.common.constant.enums.NegotiationNodeStatusEnum;
import com.aizuda.boot.modules.common.constant.enums.NegotiationStatusEnum;
import com.aizuda.boot.modules.business.contract.util.AuthUtil;
import com.aizuda.boot.modules.business.negotiation.annotation.ProcessNegotiation;
import com.aizuda.boot.modules.business.negotiation.entity.*;
import com.aizuda.boot.modules.business.negotiation.mapper.*;
import com.aizuda.boot.modules.business.contract_operation_log.service.ContractOperationLogService;
import com.aizuda.boot.modules.business.contract_operation_log.domain.entity.ContractOperationLog;
import com.aizuda.boot.modules.common.constant.enums.WorkFlowTypeEnums;
import com.aizuda.boot.modules.common.constant.enums.ActionTypeEnums;
import com.aizuda.boot.modules.common.constant.enums.SourceTypeEnums;
import com.aizuda.boot.modules.business.contract.mapper.ContractMapper;
import com.aizuda.boot.modules.business.contract.mapper.ContractFieldValueMapper;
import com.aizuda.boot.modules.business.contract.entity.ContractFieldValueEntity;
import com.aizuda.boot.modules.file.service.IContractFileService;
import com.aizuda.boot.modules.file.domain.entity.ContractFileEntity;
import com.aizuda.boot.modules.third.wps.mapper.FileHistoryMapper;
import com.aizuda.boot.modules.third.wps.domain.entity.FileHistory;
import com.aizuda.common.toolkit.JacksonUtils;
import com.aizuda.bpm.engine.FlowLongEngine;
import com.aizuda.bpm.engine.core.enums.ProcessType;
import com.aizuda.bpm.engine.entity.FlwInstance;
import com.aizuda.bpm.engine.entity.FlwProcess;
import com.aizuda.bpm.engine.entity.FlwTask;
import com.aizuda.bpm.engine.entity.FlwHisTask;
import com.aizuda.bpm.engine.entity.FlwHisInstance;
import com.aizuda.bpm.engine.model.ModelHelper;
import com.aizuda.bpm.engine.model.NodeModel;
import com.aizuda.bpm.engine.model.ProcessModel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.HashMap;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 协商流程处理AOP切面
 * 用于在审批同意时自动更新协商系统相关数据
 */
@Aspect
@Component
@Slf4j
public class NegotiationProcessAspect {
    
    @Resource
    private ContractNegotiationInstanceMapper negotiationInstanceMapper;
    
    @Resource
    private ContractNegotiationNodeInstanceMapper nodeInstanceMapper;
    
    @Resource
    private ContractNegotiationParticipantMapper participantMapper;
    
    @Resource
    private FlowLongEngine flowLongEngine;
    
    @Resource
    private ContractOperationLogService contractOperationLogService;
    
    @Resource
    private ContractMapper contractMapper;
    
    @Resource
    private ContractFieldValueMapper contractFieldValueMapper;
    
    @Resource
    private IContractFileService contractFileService;
    
    @Resource
    private FileHistoryMapper fileHistoryMapper;
    
    private final ExpressionParser parser = new SpelExpressionParser();
    
    // 用于防止重复处理的缓存，存储已处理的任务ID
    private final ConcurrentHashMap<Long, Long> processedTasks = new ConcurrentHashMap<>();
    
    /**
     * 拦截带有@ProcessNegotiation注解的方法，在审批同意后处理协商数据
     */
    @AfterReturning(
        pointcut = "@annotation(processNegotiation)",
        returning = "result"
    )
    @Transactional
    public void afterNegotiationProcess(JoinPoint joinPoint, ProcessNegotiation processNegotiation, Object result) {
        try {
            if (!processNegotiation.enabled()) {
                log.debug("ProcessNegotiation注解已禁用");
                return;
            }
            
            // 只有审批成功才处理协商逻辑
            if (!(result instanceof Boolean) || !(Boolean) result) {
                log.debug("审批未成功，跳过协商处理");
                return;
            }
            
            // 创建SpEL上下文
            StandardEvaluationContext context = createEvaluationContext(joinPoint, result);
            
            // 解析任务ID
            Long taskId = parseTaskId(processNegotiation.taskIdSource(), context);
            if (taskId == null) {
                log.warn("无法解析任务ID，表达式: {}", processNegotiation.taskIdSource());
                return;
            }
            
            // 检查流程类型，如果不是协商流程则跳过
            if (!isNegotiationProcess(taskId)) {
                log.debug("流程类型不是协商流程(business_audit)，跳过协商处理，任务ID: {}", taskId);
                return;
            }
            
            // 幂等性检查：如果任务已经处理过，跳过
            Long currentTime = System.currentTimeMillis();
            Long lastProcessTime = processedTasks.putIfAbsent(taskId, currentTime);
            if (lastProcessTime != null) {
                // 如果上次处理时间在5秒内，认为是重复处理，跳过
                if (currentTime - lastProcessTime < 5000) {
                    log.warn("任务 {} 在 {}ms 前已经处理过，跳过重复处理", taskId, currentTime - lastProcessTime);
                    return;
                } else {
                    // 超过5秒，可能是新的处理，更新时间戳
                    processedTasks.put(taskId, currentTime);
                }
            }
            
            // 处理协商逻辑
            processNegotiationData(taskId);
            
        } catch (Exception e) {
            log.error("处理协商流程失败", e);
            // 出错时从缓存中移除，允许重试
            Long taskId = parseTaskId(processNegotiation.taskIdSource(), createEvaluationContext(joinPoint, result));
            if (taskId != null) {
                processedTasks.remove(taskId);
            }
        }
    }
    
    /**
     * 创建SpEL表达式解析上下文
     */
    private StandardEvaluationContext createEvaluationContext(JoinPoint joinPoint, Object result) {
        StandardEvaluationContext context = new StandardEvaluationContext();
        
        // 设置方法参数
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();
        Parameter[] parameters = method.getParameters();
        Object[] args = joinPoint.getArgs();
        
        for (int i = 0; i < parameters.length && i < args.length; i++) {
            context.setVariable(parameters[i].getName(), args[i]);
            // 添加按位置的参数访问
            context.setVariable("p" + i, args[i]);
            // 常用参数名映射
            if (i == 0) {
                context.setVariable("dto", args[i]);
            }
        }
        
        // 设置返回值
        context.setVariable("result", result);
        context.setVariable("target", joinPoint.getTarget());
        
        return context;
    }
    
    /**
     * 解析任务ID
     */
    private Long parseTaskId(String expression, StandardEvaluationContext context) {
        try {
            Object value = parser.parseExpression(expression).getValue(context);
            if (value != null) {
                if (value instanceof Number) {
                    return ((Number) value).longValue();
                } else if (value instanceof String) {
                    return Long.parseLong((String) value);
                }
            }
        } catch (Exception e) {
            log.error("解析任务ID失败，表达式: {}", expression, e);
        }
        return null;
    }
    
    /**
     * 处理协商数据
     */
    private void processNegotiationData(Long taskId) {
        log.info("开始处理协商数据，任务ID: {}", taskId);
        
        // 获取任务信息（注意：在同意审批后，任务可能已经被删除）
        FlwTask flwTask = flowLongEngine.queryService().getTask(taskId);
        if (flwTask == null) {
            // 如果任务不存在，尝试通过历史任务获取信息
            log.warn("任务不存在，尝试从历史任务获取信息: {}", taskId);
            
            // 获取历史任务
            FlwHisTask hisTask = flowLongEngine.queryService().getHistTask(taskId);
            if (hisTask == null) {
                log.error("历史任务也不存在: {}", taskId);
                return;
            }
            
            // 使用历史任务信息继续处理
            processNegotiationDataWithHisTask(hisTask);
            return;
        }
        
        // 使用当前任务信息处理
        processNegotiationDataWithTask(flwTask);
    }
    
    /**
     * 使用当前任务信息处理协商数据
     */
    private void processNegotiationDataWithTask(FlwTask flwTask) {
        // 获取流程实例
        FlwInstance flwInstance = flowLongEngine.queryService().getInstance(flwTask.getInstanceId());
        if (flwInstance == null) {
            log.warn("流程实例不存在: {}", flwTask.getInstanceId());
            return;
        }
        
        executeNegotiationLogic(flwTask.getInstanceId(), flwTask.getTaskKey(), flwInstance);
    }
    
    /**
     * 使用历史任务信息处理协商数据
     */
    private void processNegotiationDataWithHisTask(FlwHisTask hisTask) {
        // 获取流程实例
        FlwInstance flwInstance = flowLongEngine.queryService().getInstance(hisTask.getInstanceId());
        if (flwInstance == null) {
            log.warn("流程实例不存在: {}，这是正常的，因为流程已经结束，继续使用历史数据处理", hisTask.getInstanceId());
            // 不要返回，继续执行历史数据处理逻辑
        }
        
        executeNegotiationLogic(hisTask.getInstanceId(), hisTask.getTaskKey(), flwInstance);
    }
    
    /**
     * 执行协商逻辑
     */
    private void executeNegotiationLogic(Long instanceId, String taskKey, FlwInstance flwInstance) {
        log.info("=== 开始执行协商逻辑 ===");
        log.info("参数信息 - 流程实例ID: {}, 任务Key: {}, BusinessKey: {}", 
                instanceId, taskKey, flwInstance != null ? flwInstance.getBusinessKey() : "null");
        
        // 如果流程实例不存在，尝试从历史任务获取信息
        if (flwInstance == null) {
            log.warn("流程实例不存在，尝试从历史任务获取信息: {}", instanceId);
            
            // 从历史任务中获取流程信息
            List<FlwHisTask> hisTasks = flowLongEngine.queryService().getHisTasksByInstanceId(instanceId).orElse(Collections.emptyList());
            if (hisTasks.isEmpty()) {
                log.error("无法从历史任务中获取流程信息，流程实例ID: {}", instanceId);
                return;
            }
            
            // 获取最后一个历史任务来推断流程信息
            FlwHisTask lastTask = hisTasks.get(hisTasks.size() - 1);
            String businessKey = null;
            
            // 尝试从历史任务获取businessKey
            try {
                // 查询流程实例的历史记录
                FlwHisInstance hisInstance = flowLongEngine.queryService().getHistInstance(instanceId);
                if (hisInstance != null) {
                    businessKey = hisInstance.getBusinessKey();
                    log.info("从历史流程实例获取到BusinessKey: {}", businessKey);
                } else {
                    log.warn("历史流程实例也不存在: {}", instanceId);
                    return;
                }
            } catch (Exception e) {
                log.error("获取历史流程实例失败", e);
                return;
            }
            
            // 使用历史信息继续处理
            processWithBusinessKey(instanceId, taskKey, businessKey, true);
            return;
        }
        
        // 正常流程：使用当前流程实例信息
        processWithBusinessKey(instanceId, taskKey, flwInstance.getBusinessKey(), false);
    }
    
    /**
     * 使用processInstanceId处理协商逻辑（协商流程专用）
     */
    private void processWithBusinessKey(Long instanceId, String taskKey, String businessKey, boolean isHistorical) {
        log.info("处理协商流程逻辑 - 流程实例ID: {}, 任务Key: {}, 是否历史数据: {}", 
                instanceId, taskKey, isHistorical);
        
        // 查找协商实例（仅通过processInstanceId查找，协商流程专用）
        log.info("开始查找协商实例 - 使用流程实例ID: {}", instanceId);
        
        ContractNegotiationInstanceEntity negotiationInstance = negotiationInstanceMapper.selectOne(
                new LambdaQueryWrapper<ContractNegotiationInstanceEntity>()
                        .eq(ContractNegotiationInstanceEntity::getProcessInstanceId, instanceId)
                        .eq(ContractNegotiationInstanceEntity::getNegotiationStatus, NegotiationStatusEnum.IN_NEGOTIATION.getCode())
        );
        
        log.info("通过流程实例ID查找结果: {}", negotiationInstance != null ? "找到协商实例" : "未找到协商实例");
        
        // 如果找不到协商实例，说明不是协商流程，直接返回
        if (negotiationInstance == null) {
            log.info("未找到对应的协商实例，流程实例ID: {}，这不是协商流程，跳过处理", instanceId);
            
            // 调试：查询该流程实例ID的所有协商实例状态
            List<ContractNegotiationInstanceEntity> allInstancesByProcessId = negotiationInstanceMapper.selectList(
                    new LambdaQueryWrapper<ContractNegotiationInstanceEntity>()
                            .eq(ContractNegotiationInstanceEntity::getProcessInstanceId, instanceId)
            );
            log.info("流程实例ID {} 的所有协商实例数量: {}", instanceId, allInstancesByProcessId.size());
            for (ContractNegotiationInstanceEntity instance : allInstancesByProcessId) {
                log.info("协商实例详情 - ID: {}, 状态: {}, 合同ID: {}, 流程实例ID: {}", 
                        instance.getId(), instance.getNegotiationStatus(), instance.getContractId(), instance.getProcessInstanceId());
            }
            
            return;
        }
        
        log.info("找到协商实例 - ID: {}, 状态: {}, 流程实例ID: {}", 
                negotiationInstance.getId(), negotiationInstance.getNegotiationStatus(), negotiationInstance.getProcessInstanceId());
        
        // 查询当前节点状态
        Long currentUserId = AuthUtil.getCurrentUser().getId();
        log.info("当前用户ID: {}, 协商实例ID: {}", currentUserId, negotiationInstance.getId());
        
        // 更新参与者确认状态（只更新当前节点下的参与者）
        updateParticipantConfirmStatus(negotiationInstance.getId(), currentUserId);
        
        // 协商同意后添加contract_file记录
        log.info("=== 准备创建contract_file记录 ===");
        log.info("合同ID: {}, 用户ID: {}", negotiationInstance.getContractId(), currentUserId);
        createContractFileRecord(negotiationInstance.getContractId(), currentUserId);
        log.info("=== contract_file记录创建完成 ===");
        
        // 记录确认合同的操作日志
        logContractConfirmation(negotiationInstance.getContractId(), currentUserId);
        
        // 判断当前节点是否是最后一个审批节点
        boolean isLast;
        if (isHistorical) {
            // 对于历史数据，我们认为是最后一个节点（因为流程已经完成）
            isLast = true;
            log.info("历史流程数据，判定为最后一个审批节点");
        } else {
            // 正常流程：通过流程定义判断
            FlwInstance currentInstance = flowLongEngine.queryService().getInstance(instanceId);
            isLast = isLastApprovalNodeByTaskKey(taskKey, currentInstance);
        }
        
        log.info("是否最后一个审批节点判断结果: {}", isLast);
        
        if (isLast) {
            // 最后一个节点：记录完成协商日志并完成协商
            log.info("确认为最后一个审批节点，记录完成协商日志 - 协商实例ID: {}", negotiationInstance.getId());
            logNegotiationCompletion(negotiationInstance.getContractId(), currentUserId);
            
            log.info("执行完成协商逻辑 - 协商实例ID: {}", negotiationInstance.getId());
            completeNegotiation(negotiationInstance);
        } else {
            // 不是最后节点：激活下一个节点
            log.info("不是最后一个审批节点，执行激活下一个节点逻辑 - 协商实例ID: {}", negotiationInstance.getId());
            FlwInstance currentInstance = flowLongEngine.queryService().getInstance(instanceId);
            activateNextNode(negotiationInstance, currentInstance);
        }
    }
    
    /**
     * 判断当前节点是否是最后一个审批节点（基于taskKey）
     */
    private boolean isLastApprovalNodeByTaskKey(String taskKey, FlwInstance flwInstance) {
        try {
            log.info("开始判断是否最后审批节点 - 任务Key: {}, 流程实例ID: {}, 流程定义ID: {}", 
                    taskKey, flwInstance.getId(), flwInstance.getProcessId());
            
            // 获取流程定义
            FlwProcess flwProcess = flowLongEngine.processService().getProcessById(flwInstance.getProcessId());
            if (flwProcess == null) {
                log.error("流程定义不存在 - 流程定义ID: {}", flwInstance.getProcessId());
                return false;
            }
            
            log.info("成功获取流程定义 - ID: {}, 名称: {}", flwProcess.getId(), flwProcess.getProcessName());
            
            // 解析流程模型
            ProcessModel processModel = ModelHelper.buildProcessModel(flwProcess.getModelContent());
            NodeModel rootNode = processModel.getNodeConfig();
            
            // 获取所有审批节点
            List<NodeModel> approvalNodes = new ArrayList<>();
            collectApprovalNodes(rootNode, approvalNodes);
            
            log.info("流程中审批节点总数: {}", approvalNodes.size());
            for (int i = 0; i < approvalNodes.size(); i++) {
                NodeModel node = approvalNodes.get(i);
                log.info("审批节点[{}] - Key: {}, 名称: {}", i, node.getNodeKey(), node.getNodeName());
            }
            
            // 找到当前节点在审批节点列表中的位置
            int currentIndex = -1;
            for (int i = 0; i < approvalNodes.size(); i++) {
                if (taskKey.equals(approvalNodes.get(i).getNodeKey())) {
                    currentIndex = i;
                    log.info("找到当前节点位置 - Key: {}, 位置: {}, 名称: {}", 
                            taskKey, i, approvalNodes.get(i).getNodeName());
                    break;
                }
            }
            
            if (currentIndex == -1) {
                log.warn("在审批节点列表中未找到当前任务节点 - 任务Key: {}", taskKey);
                // 也许是其他类型的节点，比如开始节点或结束节点，返回false
                return false;
            }
            
            // 如果当前节点是最后一个审批节点
            boolean isLast = currentIndex == approvalNodes.size() - 1;
            
            log.info("节点位置检查结果 - 当前节点: {}, 位置: {}/{}, 总审批节点数: {}, 是否最后节点: {}", 
                    taskKey, currentIndex + 1, approvalNodes.size(), approvalNodes.size(), isLast);
            
            return isLast;
            
        } catch (Exception e) {
            log.error("判断是否最后节点失败 - 任务Key: {}", taskKey, e);
            return false;
        }
    }
    
    /**
     * 判断当前节点是否是最后一个审批节点
     */
    private boolean isLastApprovalNode(FlwTask currentTask, FlwInstance flwInstance) {
        return isLastApprovalNodeByTaskKey(currentTask.getTaskKey(), flwInstance);
    }
    
    /**
     * 递归收集所有审批节点
     */
    private void collectApprovalNodes(NodeModel node, List<NodeModel> approvalNodes) {
        if (node == null) return;
        
        // 如果是审批节点（type = 1, 100, 101），添加到列表
        if (node.getType() != null && (node.getType() == 1 || node.getType() == 100 || node.getType() == 101)) {
            approvalNodes.add(node);
        }
        
        // 递归处理子节点
        if (node.getChildNode() != null) {
            collectApprovalNodes(node.getChildNode(), approvalNodes);
        }
    }
    
    /**
     * 完成协商流程
     */
    private void completeNegotiation(ContractNegotiationInstanceEntity negotiationInstance) {
        LocalDateTime now = LocalDateTime.now();
        
        log.info("=== 进入 completeNegotiation 方法 ===");
        log.info("开始完成协商流程 - 协商实例ID: {}, 当前时间: {}", negotiationInstance.getId(), now);
        log.info("当前线程: {}, 事务活跃状态: {}", Thread.currentThread().getName(), 
                org.springframework.transaction.support.TransactionSynchronizationManager.isActualTransactionActive());
        
        // 验证实例存在性
        ContractNegotiationInstanceEntity currentInstance = negotiationInstanceMapper.selectById(negotiationInstance.getId());
        if (currentInstance == null) {
            log.error("协商实例不存在 - ID: {}", negotiationInstance.getId());
            return;
        }
        
        log.info("当前实例状态 - ID: {}, Status: {}, 流程实例ID: {}, 更新时间: {}", 
                currentInstance.getId(), currentInstance.getNegotiationStatus(), 
                currentInstance.getProcessInstanceId(), currentInstance.getUpdatedAt());
        
        // 检查是否已经是完成状态
        if (NegotiationStatusEnum.NEGOTIATION_COMPLETE.getCode().equals(currentInstance.getNegotiationStatus())) {
            log.warn("协商实例已经是完成状态，跳过重复更新 - 实例ID: {}", negotiationInstance.getId());
            return;
        }
        
        // 更新协商实例状态 - 分步骤执行和验证
        log.info("=== 开始更新协商实例状态 ===");
        log.info("准备更新条件 - 实例ID: {}, 当前状态: {}, 目标状态: {}", 
                negotiationInstance.getId(), currentInstance.getNegotiationStatus(), NegotiationStatusEnum.NEGOTIATION_COMPLETE.getCode());
        
        try {
            int instanceUpdatedCount = negotiationInstanceMapper.update(null,
                    new LambdaUpdateWrapper<ContractNegotiationInstanceEntity>()
                            .eq(ContractNegotiationInstanceEntity::getId, negotiationInstance.getId())
                            .set(ContractNegotiationInstanceEntity::getNegotiationStatus, NegotiationStatusEnum.NEGOTIATION_COMPLETE.getCode())
                            .set(ContractNegotiationInstanceEntity::getLastConfirmTime, now)
                            .set(ContractNegotiationInstanceEntity::getUpdatedAt, now)
            );
            
            log.info("协商实例状态更新结果 - 实例ID: {}, 更新行数: {}, 目标状态: {}", 
                    negotiationInstance.getId(), instanceUpdatedCount, NegotiationStatusEnum.NEGOTIATION_COMPLETE.getCode());
            
            // 立即验证更新结果
            ContractNegotiationInstanceEntity updatedInstance = negotiationInstanceMapper.selectById(negotiationInstance.getId());
            if (updatedInstance != null) {
                log.info("更新后实例状态 - ID: {}, Status: {}, LastConfirmTime: {}", 
                        updatedInstance.getId(), updatedInstance.getNegotiationStatus(), updatedInstance.getLastConfirmTime());
                
                if (!NegotiationStatusEnum.NEGOTIATION_COMPLETE.getCode().equals(updatedInstance.getNegotiationStatus())) {
                    log.error("状态更新失败！期望状态: {}, 实际状态: {}", 
                            NegotiationStatusEnum.NEGOTIATION_COMPLETE.getCode(), updatedInstance.getNegotiationStatus());
                }
            } else {
                log.error("更新后无法查询到实例数据 - ID: {}", negotiationInstance.getId());
            }
            
        } catch (Exception e) {
            log.error("更新协商实例状态时发生异常 - 实例ID: {}", negotiationInstance.getId(), e);
            return;
        }
        
        // 查询当前节点信息
        log.info("=== 开始查询和更新当前节点 ===");
        List<ContractNegotiationNodeInstanceEntity> currentNodes = nodeInstanceMapper.selectList(
                new LambdaQueryWrapper<ContractNegotiationNodeInstanceEntity>()
                        .eq(ContractNegotiationNodeInstanceEntity::getInstanceId, negotiationInstance.getId())
                        .eq(ContractNegotiationNodeInstanceEntity::getIsCurrentNode, true)
        );
        
        log.info("当前节点查询结果 - 实例ID: {}, 当前节点数量: {}", negotiationInstance.getId(), currentNodes.size());
        for (ContractNegotiationNodeInstanceEntity node : currentNodes) {
            log.info("当前节点详情 - 节点ID: {}, 状态: {}, isCurrentNode: {}, 任务ID: {}, 排序: {}", 
                    node.getId(), node.getStatus(), node.getIsCurrentNode(), node.getTaskId(), node.getSortOrder());
        }
        
        if (currentNodes.isEmpty()) {
            log.warn("未找到当前节点，可能已经被其他线程处理了");
            return;
        }
        
        // 更新当前节点实例状态
        try {
            int nodeUpdatedCount = nodeInstanceMapper.update(null,
                    new LambdaUpdateWrapper<ContractNegotiationNodeInstanceEntity>()
                            .eq(ContractNegotiationNodeInstanceEntity::getInstanceId, negotiationInstance.getId())
                            .eq(ContractNegotiationNodeInstanceEntity::getIsCurrentNode, true)
                            .set(ContractNegotiationNodeInstanceEntity::getStatus, NegotiationNodeStatusEnum.COMPLETED.getCode())
                            .set(ContractNegotiationNodeInstanceEntity::getIsCurrentNode, false)
                            .set(ContractNegotiationNodeInstanceEntity::getFinishTime, now)
                            .set(ContractNegotiationNodeInstanceEntity::getUpdatedAt, now)
            );
            
            log.info("协商节点状态更新结果 - 实例ID: {}, 更新行数: {}, 目标状态: {}", 
                    negotiationInstance.getId(), nodeUpdatedCount, NegotiationNodeStatusEnum.COMPLETED.getCode());
            
            // 立即验证节点更新结果
            List<ContractNegotiationNodeInstanceEntity> updatedNodes = nodeInstanceMapper.selectList(
                    new LambdaQueryWrapper<ContractNegotiationNodeInstanceEntity>()
                            .eq(ContractNegotiationNodeInstanceEntity::getInstanceId, negotiationInstance.getId())
                            .orderByAsc(ContractNegotiationNodeInstanceEntity::getSortOrder)
            );
            
            log.info("更新后节点状态验证 - 实例ID: {}, 节点总数: {}", negotiationInstance.getId(), updatedNodes.size());
            for (ContractNegotiationNodeInstanceEntity node : updatedNodes) {
                log.info("节点详情 - 节点ID: {}, 状态: {}, isCurrentNode: {}, 完成时间: {}, 排序: {}", 
                        node.getId(), node.getStatus(), node.getIsCurrentNode(), node.getFinishTime(), node.getSortOrder());
            }
            
            // 验证更新结果
            if (nodeUpdatedCount == 0) {
                log.error("协商节点状态更新失败 - 可能的原因：没有当前节点或状态已变更，实例ID: {}", negotiationInstance.getId());
            }
            
        } catch (Exception e) {
            log.error("更新协商节点状态时发生异常 - 实例ID: {}", negotiationInstance.getId(), e);
        }
        
        log.info("=== completeNegotiation 方法结束 ===");
        log.info("协商流程完成处理结束 - 协商实例ID: {}", negotiationInstance.getId());
    }
    
    /**
     * 激活下一个节点
     */
    private void activateNextNode(ContractNegotiationInstanceEntity negotiationInstance, 
                                FlwInstance flwInstance) {
        LocalDateTime now = LocalDateTime.now();
        
        // 完成当前节点
        nodeInstanceMapper.update(null,
                new LambdaUpdateWrapper<ContractNegotiationNodeInstanceEntity>()
                        .eq(ContractNegotiationNodeInstanceEntity::getInstanceId, negotiationInstance.getId())
                        .eq(ContractNegotiationNodeInstanceEntity::getIsCurrentNode, true)
                        .set(ContractNegotiationNodeInstanceEntity::getStatus, NegotiationNodeStatusEnum.COMPLETED.getCode())
                        .set(ContractNegotiationNodeInstanceEntity::getIsCurrentNode, false)
                        .set(ContractNegotiationNodeInstanceEntity::getFinishTime, now)
                        .set(ContractNegotiationNodeInstanceEntity::getUpdatedAt, now)
        );
        
        // 查找下一个节点并激活
        List<ContractNegotiationNodeInstanceEntity> nodeInstances = nodeInstanceMapper.selectList(
                new LambdaQueryWrapper<ContractNegotiationNodeInstanceEntity>()
                        .eq(ContractNegotiationNodeInstanceEntity::getInstanceId, negotiationInstance.getId())
                        .eq(ContractNegotiationNodeInstanceEntity::getStatus, NegotiationNodeStatusEnum.NOT_START.getCode())
                        .orderByAsc(ContractNegotiationNodeInstanceEntity::getSortOrder)
                        .last("LIMIT 1")
        );
        
        if (!nodeInstances.isEmpty()) {
            ContractNegotiationNodeInstanceEntity nextNode = nodeInstances.get(0);
            
            // 激活下一个节点
            nodeInstanceMapper.update(null,
                    new LambdaUpdateWrapper<ContractNegotiationNodeInstanceEntity>()
                            .eq(ContractNegotiationNodeInstanceEntity::getId, nextNode.getId())
                            .set(ContractNegotiationNodeInstanceEntity::getStatus, NegotiationNodeStatusEnum.PROCESSING.getCode())
                            .set(ContractNegotiationNodeInstanceEntity::getIsCurrentNode, true)
                            .set(ContractNegotiationNodeInstanceEntity::getStartTime, now)
                            .set(ContractNegotiationNodeInstanceEntity::getUpdatedAt, now)
            );
            
            // 获取下一个任务的ID并更新
            updateNextTaskId(flwInstance.getId(), nextNode);
            
            log.info("激活下一个协商节点 - 节点ID: {}, 角色ID: {}", nextNode.getId(), nextNode.getRoleId());
        } else {
            log.warn("未找到下一个待激活的协商节点 - 协商实例ID: {}", negotiationInstance.getId());
        }
    }
    
    /**
     * 更新下一个节点的任务ID
     */
    private void updateNextTaskId(Long instanceId, ContractNegotiationNodeInstanceEntity nextNode) {
        try {
            // 获取流程实例的所有当前任务
            List<FlwTask> tasks = flowLongEngine.queryService().getTasksByInstanceId(instanceId);
            
            if (!tasks.isEmpty()) {
                // 由于同一时间只有当前活跃节点的任务存在，
                // 我们需要找到与下一个节点对应的任务
                
                FlwTask matchedTask = null;
                
                // 尝试多种匹配策略
                for (FlwTask task : tasks) {
                    log.info("检查任务 - 任务ID: {}, 任务Key: {}, 任务名称: {}", 
                            task.getId(), task.getTaskKey(), task.getTaskName());
                    
                    // 如果只有一个任务，很可能就是下一个节点的任务
                    if (tasks.size() == 1) {
                        matchedTask = task;
                        log.info("只有一个活跃任务，直接匹配 - 任务ID: {}", task.getId());
                        break;
                    }
                    
                    // TODO: 这里可以添加更复杂的匹配逻辑
                    // 比如通过任务Key、任务名称等来匹配
                    // 暂时使用第一个任务
                    if (matchedTask == null) {
                        matchedTask = task;
                    }
                }
                
                if (matchedTask != null) {
                    // 更新节点的任务ID
                    nodeInstanceMapper.update(null,
                            new LambdaUpdateWrapper<ContractNegotiationNodeInstanceEntity>()
                                    .eq(ContractNegotiationNodeInstanceEntity::getId, nextNode.getId())
                                    .set(ContractNegotiationNodeInstanceEntity::getTaskId, matchedTask.getId())
                    );
                    
                    log.info("成功更新下一个节点的任务ID - 节点ID: {}, 节点排序: {}, 任务ID: {}", 
                            nextNode.getId(), nextNode.getSortOrder(), matchedTask.getId());
                } else {
                    log.warn("未找到匹配的任务 - 节点ID: {}, 节点排序: {}", 
                            nextNode.getId(), nextNode.getSortOrder());
                }
            } else {
                log.warn("流程实例没有活跃任务 - 实例ID: {}, 节点ID: {}", instanceId, nextNode.getId());
            }
        } catch (Exception e) {
            log.error("更新下一个节点任务ID失败 - 节点ID: {}", nextNode.getId(), e);
        }
    }
    
    /**
     * 更新参与者确认状态（只更新当前节点下的参与者）
     */
    private void updateParticipantConfirmStatus(Integer negotiationInstanceId, Long currentUserId) {
        // 查询当前节点
        List<ContractNegotiationNodeInstanceEntity> currentNodes = nodeInstanceMapper.selectList(
                new LambdaQueryWrapper<ContractNegotiationNodeInstanceEntity>()
                        .eq(ContractNegotiationNodeInstanceEntity::getInstanceId, negotiationInstanceId)
                        .eq(ContractNegotiationNodeInstanceEntity::getIsCurrentNode, true)
        );
        
        log.info("当前节点数量: {}", currentNodes.size());
        for (ContractNegotiationNodeInstanceEntity node : currentNodes) {
            log.info("当前节点 - ID: {}, 角色ID: {}, 状态: {}, 排序: {}", 
                    node.getId(), node.getRoleId(), node.getStatus(), node.getSortOrder());
        }
        
        // 更新当前参与者确认状态 - 修正：只更新当前节点下的参与者
        int updatedCount = 0;
        if (!currentNodes.isEmpty()) {
            // 获取当前节点的ID（通常只有一个当前节点）
            ContractNegotiationNodeInstanceEntity currentNode = currentNodes.get(0);
            
            // 只更新当前节点下的该用户参与者记录
            updatedCount = participantMapper.update(null,
                    new LambdaUpdateWrapper<ContractNegotiationParticipantEntity>()
                            .eq(ContractNegotiationParticipantEntity::getInstanceId, negotiationInstanceId)
                            .eq(ContractNegotiationParticipantEntity::getNodeInstanceId, currentNode.getId()) // 关键修复：增加节点实例ID匹配
                            .eq(ContractNegotiationParticipantEntity::getEmployeeId, currentUserId)
                            .eq(ContractNegotiationParticipantEntity::getIsConfirmed, false)
                            .set(ContractNegotiationParticipantEntity::getIsConfirmed, true)
                            .set(ContractNegotiationParticipantEntity::getConfirmedTime, LocalDateTime.now())
                            .set(ContractNegotiationParticipantEntity::getUpdatedAt, LocalDateTime.now())
            );
            
            log.info("更新参与者确认状态 - 当前节点ID: {}, 当前用户ID: {}, 更新数量: {}", 
                    currentNode.getId(), currentUserId, updatedCount);
        } else {
            log.warn("未找到当前节点，无法更新参与者确认状态");
        }
    }
    
    /**
     * 定期清理过期的任务缓存（每30分钟执行一次）
     */
    @Scheduled(fixedRate = 30 * 60 * 1000) // 30分钟
    public void cleanupExpiredTaskCache() {
        try {
            long now = System.currentTimeMillis();
            long expirationTime = 60 * 60 * 1000; // 1小时过期
            
            processedTasks.entrySet().removeIf(entry -> {
                boolean shouldRemove = now - entry.getValue() > expirationTime;
                if (shouldRemove) {
                    log.debug("清理过期的任务缓存：任务ID {}", entry.getKey());
                }
                return shouldRemove;
            });
            
            log.info("任务缓存清理完成，当前缓存大小：{}", processedTasks.size());
        } catch (Exception e) {
            log.error("清理任务缓存失败", e);
        }
    }
    
    /**
     * 记录确认合同的操作日志
     * @param contractId 合同ID
     * @param userId 用户ID
     */
    private void logContractConfirmation(Integer contractId, Long userId) {
        try {
            log.info("=== 开始记录确认合同日志 ===");
            log.info("参数 - 合同ID: {}, 用户ID: {}", contractId, userId);
            
            // 从动态字段获取主合同文件ID（字段ID=20）
            Long mainContractFileId = getMainContractFileId(contractId);
            log.info("从动态字段查询到主合同文件ID: {}", mainContractFileId);
            
            // 构建扩展数据
            Map<String, Object> extData = new HashMap<>();
            if (mainContractFileId != null) {
                log.info("主合同文件ID不为空，开始构建扩展数据: {}", mainContractFileId);
                
                extData.put("mainContractFileId", mainContractFileId);
                
                // 获取文件版本信息
                String version = getFileVersionInfo(contractId, mainContractFileId);
                if (version != null) {
                    extData.put("version", version);
                    log.info("添加版本信息到扩展数据: {}", version);
                } else {
                    log.info("未获取到版本信息，不添加version字段");
                }
            } else {
                log.warn("主合同文件ID为空，不添加文件相关的扩展数据，合同ID: {}", contractId);
            }
            
            // 构建日志数据
            ContractOperationLog operationLog = ContractOperationLog.builder()
                    .contractId(contractId.longValue())
                    .flowType(WorkFlowTypeEnums.NEGOTIATION_WORKFLOW.getCode())
                    .actionType(ActionTypeEnums.CONFIRM_CONTRACT.getCode())
                    .sourceType(SourceTypeEnums.USER.getCode())
                    .userId(userId)
                    .actionTime(new Date())
                    .extData(JacksonUtils.toJson(extData))
                    .build();
            
            // 保存日志
            contractOperationLogService.save(operationLog);
            log.info("记录确认合同日志成功，合同ID: {}, 用户ID: {}, ext_data: {}", 
                    contractId, userId, operationLog.getExtData());
            
        } catch (Exception e) {
            log.error("记录确认合同日志失败，合同ID: {}, 用户ID: {}", contractId, userId, e);
        }
    }
    
    /**
     * 记录完成协商的操作日志
     * @param contractId 合同ID
     * @param userId 用户ID
     */
    private void logNegotiationCompletion(Integer contractId, Long userId) {
        try {
            // 构建日志数据
            ContractOperationLog operationLog = ContractOperationLog.builder()
                    .contractId(contractId.longValue())
                    .flowType(WorkFlowTypeEnums.NEGOTIATION_WORKFLOW.getCode())
                    .actionType(ActionTypeEnums.COMPLETE_NEGOTIATION.getCode())
                    .sourceType(SourceTypeEnums.USER.getCode())
                    .userId(userId)
                    .actionTime(new Date())
                    .build();
            
            // 保存日志
            contractOperationLogService.save(operationLog);
            log.info("记录完成协商日志成功，合同ID: {}, 用户ID: {}", contractId, userId);
            
        } catch (Exception e) {
            log.error("记录完成协商日志失败，合同ID: {}, 用户ID: {}", contractId, userId, e);
        }
    }

    /**
     * 协商同意后创建合同文件记录
     * 
     * @param contractId 合同ID
     * @param userId 当前用户ID
     */
    private void createContractFileRecord(Integer contractId, Long userId) {
        try {
            log.info("开始创建合同文件记录，合同ID: {}, 用户ID: {}", contractId, userId);
            
            // 1. 获取当前合同的主合同文件ID（动态字段ID=20）
            Long mainContractFileId = getMainContractFileId(contractId);
            if (mainContractFileId == null) {
                log.warn("未找到合同的主合同文件，合同ID: {}", contractId);
                return;
            }
            
            log.info("获取到主合同文件ID: {}", mainContractFileId);
            
            // 2. 查找当前合同的最高major_version
            Integer currentMajorVersion = getCurrentMaxMajorVersion(contractId, mainContractFileId);
            log.info("当前最高major_version: {}", currentMajorVersion);
            
            // 3. 查找当前major_version下最高的minor_version，然后+1
            Integer newMinorVersion = getNextMinorVersion(contractId, mainContractFileId, currentMajorVersion);
            log.info("新的minor_version: {}", newMinorVersion);
            
            // 4. 获取file_history表中该文件的最高版本号
            Integer fileHistoryVersion = getMaxFileHistoryVersion(mainContractFileId);
            log.info("文件历史版本号: {}", fileHistoryVersion);
            
            // 5. 创建contract_file记录
            ContractFileEntity contractFile = new ContractFileEntity()
                    .setContractId(contractId)
                    .setMajorVersion(currentMajorVersion)
                    .setMinorVersion(newMinorVersion)
                    .setFileId(mainContractFileId)
                    .setCreateId(userId)
                    .setUpdateBy(userId)
                    .setCreateTime(LocalDateTime.now())
                    .setUpdateTime(LocalDateTime.now());
            
            // 只有在找到有效的文件历史版本时才设置该字段
            if (fileHistoryVersion != null) {
                contractFile.setFileHistoryVersion(fileHistoryVersion);
                log.info("设置文件历史版本号: {}", fileHistoryVersion);
            } else {
                log.info("未设置文件历史版本号（未找到有效数据）");
            }
            
            contractFileService.save(contractFile);
            
            log.info("协商同意后合同文件记录创建成功，合同ID: {}, 文件ID: {}, 版本: {}.{}, 历史版本: {}", 
                    contractId, mainContractFileId, currentMajorVersion, newMinorVersion, fileHistoryVersion);
            
        } catch (Exception e) {
            log.error("创建合同文件记录失败，合同ID: {}, 用户ID: {}", contractId, userId, e);
            // 不抛出异常，避免影响主流程
        }
    }
    
    /**
     * 获取合同的主合同文件ID（动态字段ID=20）
     * 
     * @param contractId 合同ID
     * @return 主合同文件ID
     */
    private Long getMainContractFileId(Integer contractId) {
        try {
            ContractFieldValueEntity fieldValue = contractFieldValueMapper.selectOne(
                    new LambdaQueryWrapper<ContractFieldValueEntity>()
                            .eq(ContractFieldValueEntity::getContractId, contractId)
                            .eq(ContractFieldValueEntity::getFieldId, 20L) // 主合同文件字段ID
            );
            
            if (fieldValue != null && fieldValue.getFieldValue() != null) {
                return Long.parseLong(fieldValue.getFieldValue());
            }
            
            return null;
        } catch (Exception e) {
            log.error("获取主合同文件ID失败，合同ID: {}", contractId, e);
            return null;
        }
    }
    
    /**
     * 获取当前合同指定文件的最高major_version
     * 
     * @param contractId 合同ID
     * @param fileId 文件ID
     * @return 最高major_version
     */
    private Integer getCurrentMaxMajorVersion(Integer contractId, Long fileId) {
        try {
            ContractFileEntity latestVersion = contractFileService.getOne(
                    new LambdaQueryWrapper<ContractFileEntity>()
                            .eq(ContractFileEntity::getContractId, contractId)
                            .eq(ContractFileEntity::getFileId, fileId)
                            .orderByDesc(ContractFileEntity::getMajorVersion)
                            .last("LIMIT 1")
            );
            
            return latestVersion != null ? latestVersion.getMajorVersion() : 1;
        } catch (Exception e) {
            log.error("获取最高major_version失败，合同ID: {}, 文件ID: {}", contractId, fileId, e);
            return 1; // 默认返回1
        }
    }
    
    /**
     * 获取指定major_version下的下一个minor_version
     * 
     * @param contractId 合同ID
     * @param fileId 文件ID
     * @param majorVersion 主版本号
     * @return 下一个minor_version
     */
    private Integer getNextMinorVersion(Integer contractId, Long fileId, Integer majorVersion) {
        try {
            ContractFileEntity latestMinorVersion = contractFileService.getOne(
                    new LambdaQueryWrapper<ContractFileEntity>()
                            .eq(ContractFileEntity::getContractId, contractId)
                            .eq(ContractFileEntity::getFileId, fileId)
                            .eq(ContractFileEntity::getMajorVersion, majorVersion)
                            .orderByDesc(ContractFileEntity::getMinorVersion)
                            .last("LIMIT 1")
            );
            
            return latestMinorVersion != null ? latestMinorVersion.getMinorVersion() + 1 : 1;
        } catch (Exception e) {
            log.error("获取下一个minor_version失败，合同ID: {}, 文件ID: {}, 主版本: {}", contractId, fileId, majorVersion, e);
            return 1; // 默认返回1
        }
    }
    
    /**
     * 获取file_history表中指定文件的最高版本号
     * 
     * @param fileId 文件ID
     * @return 最高版本号（整数形式），如果没有数据或version为空则返回null
     */
    private Integer getMaxFileHistoryVersion(Long fileId) {
        try {
            FileHistory latestHistory = fileHistoryMapper.selectOne(
                    new LambdaQueryWrapper<FileHistory>()
                            .eq(FileHistory::getFileId, fileId)
                            .isNotNull(FileHistory::getVersion) // 只查询version不为空的记录
                            .orderByDesc(FileHistory::getVersion)
                            .last("LIMIT 1")
            );
            
            if (latestHistory != null && latestHistory.getVersion() != null) {
                log.info("找到文件历史版本，文件ID: {}, 版本号: {}", fileId, latestHistory.getVersion());
                return latestHistory.getVersion();
            } else {
                log.info("未找到文件历史版本数据或version为空，文件ID: {}", fileId);
                return null;
            }
        } catch (Exception e) {
            log.error("获取文件历史最高版本失败，文件ID: {}", fileId, e);
            return null;
        }
    }
    
    /**
     * 获取文件版本信息
     * 
     * @param contractId 合同ID
     * @param fileId 文件ID
     * @return 版本信息，格式为"主合同 V{major_version}.{minor_version}"，如果没有找到则返回null
     */
    private String getFileVersionInfo(Integer contractId, Long fileId) {
        try {
            // 查询该文件的最高版本记录
            LambdaQueryWrapper<ContractFileEntity> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(ContractFileEntity::getContractId, contractId)
                    .eq(ContractFileEntity::getFileId, fileId)
                    .orderByDesc(ContractFileEntity::getMajorVersion)
                    .orderByDesc(ContractFileEntity::getMinorVersion)
                    .last("LIMIT 1");
            
            ContractFileEntity latestVersion = contractFileService.getOne(queryWrapper);
            
            if (latestVersion != null) {
                return String.format("主合同 V%d.%d", 
                        latestVersion.getMajorVersion(), 
                        latestVersion.getMinorVersion());
            }
            
            // 如果没有版本记录，返回null
            log.info("未找到文件版本记录，不添加版本信息，合同ID: {}, 文件ID: {}", contractId, fileId);
            return null;
            
        } catch (Exception e) {
            log.error("获取文件版本信息失败，不添加版本信息，合同ID: {}, 文件ID: {}", contractId, fileId, e);
            return null;
        }
    }

    /**
     * 检查是否为协商流程（根据process_type判断）
     */
    private boolean isNegotiationProcess(Long taskId) {
        try {
            // 1. 通过taskId获取FlwTask
            FlwTask flwTask = flowLongEngine.queryService().getTask(taskId);
            if (flwTask == null) {
                // 如果任务不存在，尝试从历史任务获取
                FlwHisTask hisTask = flowLongEngine.queryService().getHistTask(taskId);
                if (hisTask == null) {
                    log.warn("任务和历史任务都不存在，任务ID: {}", taskId);
                    return false;
                }
                return isNegotiationProcessByInstanceId(hisTask.getInstanceId());
            }
            
            return isNegotiationProcessByInstanceId(flwTask.getInstanceId());
            
        } catch (Exception e) {
            log.error("检查流程类型失败，任务ID: {}", taskId, e);
            return false;
        }
    }
    
    /**
     * 根据流程实例ID检查是否为协商流程
     */
    private boolean isNegotiationProcessByInstanceId(Long instanceId) {
        try {
            // 2. 通过instanceId获取FlwInstance
            FlwInstance flwInstance = flowLongEngine.queryService().getInstance(instanceId);
            Long processId;
            
            if (flwInstance == null) {
                // 如果流程实例不存在，尝试从历史流程实例获取
                FlwHisInstance hisInstance = flowLongEngine.queryService().getHistInstance(instanceId);
                if (hisInstance == null) {
                    log.warn("流程实例和历史流程实例都不存在，实例ID: {}", instanceId);
                    return false;
                }
                processId = hisInstance.getProcessId();
            } else {
                processId = flwInstance.getProcessId();
            }
            
            // 3. 通过processId获取FlwProcess
            FlwProcess flwProcess = flowLongEngine.processService().getProcessById(processId);
            if (flwProcess == null) {
                log.warn("流程定义不存在，流程ID: {}", processId);
                return false;
            }
            
            // 4. 检查process_type
            String processType = flwProcess.getProcessType();
            log.debug("流程类型检查 - 流程ID: {}, 流程类型: {}", processId, processType);
            
            // 只有process_type为business_audit的流程才需要执行协商逻辑
            return ProcessType.business_audit.eq(processType);
            
        } catch (Exception e) {
            log.error("根据实例ID检查流程类型失败，实例ID: {}", instanceId, e);
            return false;
        }
    }
} 